package com.zhuifeng.orders.service.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSONObject;
import com.zhuifeng.common.core.constant.CacheConstants;
import com.zhuifeng.common.core.domain.R;
import com.zhuifeng.common.core.utils.DateUtils;
import com.zhuifeng.common.core.utils.JwtUtils;
import com.zhuifeng.common.core.utils.StringUtils;
import com.zhuifeng.common.core.utils.snow.GuuidUtil;
import com.zhuifeng.common.redis.service.RedisService;
import com.zhuifeng.common.security.utils.SecurityUtils;
import com.zhuifeng.orders.controller.SiteController;
import com.zhuifeng.orders.domain.OrdersDetails;
import com.zhuifeng.orders.domain.OrdersEcho;
import com.zhuifeng.orders.domain.SubMitOrders;
import com.zhuifeng.orders.mapper.OrdersDetailsMapper;
import com.zhuifeng.product.domain.ProductRultAttrCenter;
import com.zhuifeng.system.domain.model.LoginUser;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RReadWriteLock;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;
import com.zhuifeng.orders.mapper.OrdersMapper;
import com.zhuifeng.orders.domain.Orders;
import com.zhuifeng.orders.service.IOrdersService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

/**
 * 订单Service业务层处理
 * 
 * @author zhuifeng
 * @date 2022-08-18
 */
@Service
public class OrdersServiceImpl implements IOrdersService 
{
    @Autowired
    private OrdersMapper ordersMapper;
    @Autowired
    private OrdersDetailsMapper ordersDetailsMapper;
    private final HttpServletRequest request;
    @Autowired
    private RedisService redisService;
    private final StringRedisTemplate redisTemplate;
    private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
    private final SiteController siteController;
    private final Redisson redisson;
    private final RabbitTemplate rabbitTemplate;




    public OrdersServiceImpl(HttpServletRequest request, StringRedisTemplate redisTemplate, SiteController siteController, Redisson redisson, RabbitTemplate rabbitTemplate) {
        this.request = request;
        this.redisTemplate = redisTemplate;
        this.siteController = siteController;
        this.redisson = redisson;
        this.rabbitTemplate = rabbitTemplate;
    }

    /**
     * 查询订单
     * 
     * @param ordersId 订单主键
     * @return 订单
     */
    @Override
    public Orders selectOrdersByOrdersId(String ordersId)
    {
        return ordersMapper.selectOrdersByOrdersId(ordersId);
    }

    /**
     * 查询订单列表
     * 
     * @param orders 订单
     * @return 订单
     */
    @Override
    public List<Orders> selectOrdersList(Orders orders)
    {
        //获取当前登录人
        LoginUser user=null;
        {
            String token = SecurityUtils.getToken(request);
            if (StringUtils.isNotEmpty(token)){
                String userKey = JwtUtils.getUserKey(token);
                user=redisService.getCacheObject(getTokenKey(userKey));
            }
        }
        orders.setUserId(user.getUserid()+"");
        System.out.println(user);
        return ordersMapper.selectOrdersList(orders);
    }

    /**
     * 新增订单
     * 
     * @param orders 订单
     * @return 结果
     */
    @Override
    public int insertOrders(Orders orders)
    {
        //当前日期
        orders.setCreateTime(DateUtils.getNowDate());
        //雪花算法生成订单编号
        orders.setOrdersId(GuuidUtil.getUUID()+"");
        return ordersMapper.insertOrders(orders);
    }

    /**
     * 修改订单
     * 
     * @param orders 订单
     * @return 结果
     */
    @Override
    public int updateOrders(Orders orders)
    {
        orders.setUpdateTime(DateUtils.getNowDate());
        return ordersMapper.updateOrders(orders);
    }

    /**
     * 批量删除订单
     * 
     * @param ordersIds 需要删除的订单主键
     * @return 结果
     */
    @Override
    public int deleteOrdersByOrdersIds(String[] ordersIds)
    {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        //根据订单id查询订单详情
        List<OrdersDetails> ordersDetails=this.ordersDetailsMapper.selectOrdersDetails(ordersIds);
        //在缓存中将库存加回来
        for (OrdersDetails ordersDetail : ordersDetails) {
            //redis写锁
            RReadWriteLock readWriteLock = redisson.getReadWriteLock(ordersDetail.getProductId());
            RLock writeLock = readWriteLock.writeLock();
            writeLock.lock();

            String key="product"+ordersDetail.getProductId();

            ops.increment(key, ordersDetail.getOrdersDetailsProductNum());
            //修改数据库库存
            OrdersDetails ordersDetails1 = new OrdersDetails();
            ordersDetails1.setOrdersDetailsProductNum(ordersDetail.getOrdersDetailsProductNum());
            ordersDetails1.setProductId(ordersDetail.getProductId());
            String ordersDetailsJson = JSONObject.toJSONString(ordersDetails1);
            //发送mq
            rabbitTemplate.convertAndSend("zhuifeng_deduction_inventory",ordersDetailsJson);
            //落锁
            writeLock.unlock();
        }
        //删除订单详情
        this.ordersDetailsMapper.updateOrdersDetailsId(ordersIds);
        //删除订单
        return ordersMapper.deleteOrdersByOrdersIds(ordersIds);
    }

    /**
     * 删除订单信息
     * 
     * @param ordersId 订单主键
     * @return 结果
     */
    @Override
    public int deleteOrdersByOrdersId(String ordersId)
    {
        return ordersMapper.deleteOrdersByOrdersId(ordersId);
    }

    @Override
    public R confirmReceiptUpdateState(String orderId) {
        //修改订单状态
        this.ordersMapper.confirmReceiptUpdateState(orderId);
        return R.ok();
    }

    /**
     * 根据id查询sku信息
     * @param productSkuId
     * @return
     */
    @Override
    public OrdersEcho selectProductSkuId(String productSkuId) {

        //根据商品id查询商品信息
        OrdersEcho ordersEchos=this.ordersMapper.selectProductId(productSkuId);
        ordersEchos.setProductName(ordersEchos.getProductName()+ordersEchos.getSku());
        return ordersEchos;
    }

    /**
     * 生成令牌桶
     * @return
     */
    @Override
    public List<String> createToken() {
        List<String> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            list.add(GuuidUtil.getUUID()+"");
        }
        return list;
    }

    @Override
    public String getToken(List<String> token) {
        Random random = new Random();
        int i = random.nextInt(1000);
        String s = token.get(i);
        redisTemplate.opsForValue().set(s,s,30, TimeUnit.MINUTES);
        return s;
    }

    /**
     * 订单生成
     * @param subMitOrders
     * @return
     */
    @Transactional
    @Override
    public R subMitOrdersCreate(SubMitOrders subMitOrders) {
        //防止恶意下单
        String token = redisTemplate.opsForValue().get(subMitOrders.getOrdersToken());
        if (token==null){
            return R.fail();
        }
        redisTemplate.delete(token);

        //查询出商品的库存  假设商品的库存为5
        long productInventory = 5;
        //将库存存入redis中
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        String key="product"+subMitOrders.getProductId();
        ops.set(key,5+"",30,TimeUnit.MINUTES);
        //判断商品是否充足
        if (productInventory < subMitOrders.getOrdersDetailsProductNum()){
            return R.fail("库存不足");
        }

        Long value = ops.increment(key, -subMitOrders.getOrdersDetailsProductNum());
        if (value >= 0){
            //生成订单编号
            long uuid = GuuidUtil.getUUID();
            //获取当前登录人
            LoginUser user = this.siteController.selectUser();
            //订单信息
            Orders orders = new Orders();
            orders.setUserId(user.getUserid()+"");
            orders.setOrdersId(uuid+"");
            orders.setOrdersPriceSum(subMitOrders.getOrdersPriceSum());
            orders.setOrdersPayPrice(subMitOrders.getOrdersPayPrice());
            orders.setOrdersState(1);
            orders.setSiteId(subMitOrders.getSiteId());
            orders.setOrdersSource(1);
            orders.setOrdersPayWay(subMitOrders.getOrdersPayWay());
            //添加订单
            this.ordersMapper.addOrders(orders);
            //添加订单详情
            OrdersDetails ordersDetails = new OrdersDetails();
            ordersDetails.setOrdersDetailsId(GuuidUtil.getUUID()+"");
            ordersDetails.setOrdersId(uuid+"");
            ordersDetails.setProductId(subMitOrders.getProductId());
            ordersDetails.setOrdersDetailsProductPrice(subMitOrders.getOrdersDetailsProductPrice());
            ordersDetails.setOrdersDetailsProductNum(subMitOrders.getOrdersDetailsProductNum());
            this.ordersMapper.addOrdersDetails(ordersDetails,user.getUserid());
            //mq发送减库存
            OrdersDetails ordersDetails1 = new OrdersDetails();
            ordersDetails1.setProductId(subMitOrders.getProductId());
            ordersDetails1.setOrdersDetailsProductNum(subMitOrders.getOrdersDetailsProductNum());
            String ordersDetailsJson = JSONObject.toJSONString(ordersDetails1);
            rabbitTemplate.convertAndSend("zhuifeng_subtract_inventory",ordersDetailsJson);
            return R.ok();

        }else{
            //库存不足，需要增加刚刚减去的库存
             ops.increment(key, subMitOrders.getOrdersDetailsProductNum().longValue());
             return R.fail();
        }
    }

    /**
     * 确认收货
     * @param ordersIds
     * @return
     */
    @Override
    public int affirmReceivingOrdersByOrdersIds(String[] ordersIds) {
        ValueOperations<String, String> ops = redisTemplate.opsForValue();
        //根据订单id查询订单详情
        List<OrdersDetails> ordersDetails=this.ordersDetailsMapper.selectOrdersDetails(ordersIds);
        for (OrdersDetails ordersDetail : ordersDetails) {
            //写锁
            String key = "product"+ordersDetail.getProductId();
            RReadWriteLock readWriteLock = redisson.getReadWriteLock(key);
            RLock readLock = readWriteLock.readLock();
            readLock.lock();
//            ops.increment(key,ordersDetail.getOrdersDetailsProductNum().longValue());
            //数据库订单减库存
            OrdersDetails ordersDetails1 = new OrdersDetails();
            ordersDetails1.setProductId(ordersDetail.getProductId());
            ordersDetails1.setOrdersDetailsProductNum(ordersDetail.getOrdersDetailsProductNum());
            String ordersDetailsJson = JSONObject.toJSONString(ordersDetail);
            rabbitTemplate.convertAndSend("affirm_receiving",ordersDetailsJson);
            //落锁
            readLock.unlock();
        }
        return 0;
    }

    /**
     * 获取token
     * @param token
     * @return
     */
    private String getTokenKey(String token)
    {
        return ACCESS_TOKEN + token;
    }
}
